package me.zhengjie.ppService;

import cn.hutool.core.util.ObjectUtil;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.pojo.InBoundInfo;
import me.zhengjie.pojo.Resp;
import me.zhengjie.pojo.sqlServer.*;
import me.zhengjie.repository.*;
import me.zhengjie.service.PPOutboundOrderService;
import me.zhengjie.service.PPStorageService;
import me.zhengjie.wcs.PPWmsToWcs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author krilo
 * @date 2024-08-22 11:17
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "模拟码垛机执行任务")
public class ImitationTestService {

    private final PPTaskResultRepository ppTaskResultRepository;
    private final PPInboundMissionHistoryRepository ppInoundMissionHistoryRepository;
    private final PPOutboundMissionHistoryRepository ppOutBoundMissionHistoryRepository;
    private final PPStorageService ppStorageService;
    private final PpPalletRepository ppPalletRepository;
    private final PPTaskResultService ppTaskResultService;
    private final PPInventoryService ppInventoryService;
    private final PPOutboundMissionRepository ppOutBoundMissionRepository;
    private final PPOutboundOrderService ppOutBoundOrderService;
    private final PPInfoRepository ppInfoRepository;
    private final PPMoveMissionRepository ppMoveMissionRepository;
    private final PPInventoryRepository ppInventoryRepository;
    private final PPWmsToWcs ppWmsToWcs;
    private final PPWmsTaskRepository ppWmsTaskRepository;
    private final PPInBoundService ppInBoundService;
    private final PPInboundMissionRepository ppInoundMissionRepository;
    private final PpPalletService ppPalletService;
    private final PPMoveService ppMoveService;
    private final PPStationRepository ppStationRepository;
    private final PPStationService ppStationService;
    private final PPOutBoundService ppOutBoundService;
    private final PPOutboundMissionRepository ppOutboundMissionRepository;
    private final Lock lock = new ReentrantLock();

    private static final Logger ppLog = LoggerFactory.getLogger("pp");

    //模拟发送出库任务到wcs
    @Transactional
    public Resp sendOutBoundtask() {

        if (lock.tryLock()) {
            try {
                //查询有无空闲的站点
                List<PPStation> freeStations = ppStationService.findFreeStation();
                PPOutboundMission newPPOutboundMission = ppOutBoundService.findNewOutBoundMission();

                //查看是否有分配终点
                if (newPPOutboundMission.getDestination() == null && freeStations.size() > 0) {
                    //任务分配终点
                    newPPOutboundMission.setDestination(freeStations.get(0).getStationCode());
                    ppOutboundMissionRepository.save(newPPOutboundMission);

                    //锁对应的工作站
                    ppStationService.lockStation(newPPOutboundMission.getDestination());

                    //创建pp_wms_task
                    List<PPOutboundMission> ppOutBoundMissions = new ArrayList<>();
                    ppOutBoundMissions.add(newPPOutboundMission);
                    // ppOutBoundService.createOutTask(ppOutBoundMissions);

                    PPWmsTask ppWmsTask = ppWmsTaskRepository.findPPWmsTasksByWmsTaskId(newPPOutboundMission.getMissionCode());

                    saveTaskResult(ppWmsTask);
                    ppWmsToWcs.saveToMissionHistory(ppWmsTask, 2);

                    return Resp.builder()
                            .status(200)
                            .msg("发送成功")
                            .build();
                }

                if (newPPOutboundMission.getDestination() != null && freeStations.size() > 0) {

                    //查看Destination的储位是否被锁了
                    if (ppStationRepository.findPPStationsByStationCode(newPPOutboundMission.getDestination()).getTakeStatus() == 1) {
                        return Resp.builder()
                                .status(500)
                                .msg(newPPOutboundMission.getDestination() + "工作站被锁定,发送出库任务失败")
                                .build();
                    }

                    //锁对应的工作站
                    ppStationService.lockStation(newPPOutboundMission.getDestination());

                    //创建pp_wms_task
                    List<PPOutboundMission> ppOutBoundMissions = new ArrayList<>();
                    ppOutBoundMissions.add(newPPOutboundMission);
                    // ppOutBoundService.createOutTask(ppOutBoundMissions);

                    PPWmsTask ppWmsTask = ppWmsTaskRepository.findPPWmsTasksByWmsTaskId(newPPOutboundMission.getMissionCode());

                    saveTaskResult(ppWmsTask);
                    ppWmsToWcs.saveToMissionHistory(ppWmsTask, 2);
                    return Resp.builder()
                            .status(200)
                            .msg("发送成功")
                            .build();


                }

                return Resp.builder()
                        .status(500)
                        .msg("发送失败")
                        .build();


            } finally {
                lock.unlock();
            }
        } else {
            // 处理无法获取锁的情况，例如记录日志或稍后重试
            ppLog.warn("无法获取锁，任务将被跳过");
            return Resp.builder()
                    .status(500)
                    .msg("无法获取锁,发送失败")
                    .build();
        }


    }


    //模拟发送入库任务到wcs
    @Transactional
    public Resp sendInBoundtask() {
        if (ppInoundMissionRepository.findAll().size() != 0) {
            PPInboundMission ppInboundMission = ppInBoundService.findNewInBoundMission();
            PPWmsTask ppWmsTask = ppInBoundService.getPPWmsTask(ppInboundMission);

            saveTaskResult(ppWmsTask);
            ppWmsToWcs.saveToMissionHistory(ppWmsTask, 1);
            ppInoundMissionRepository.deletePPInboundMissionByMissionCode(ppWmsTask.getWmsTaskId());
            return Resp.builder()
                    .status(200)
                    .msg("发送成功")
                    .build();
        } else {
            return Resp.builder()
                    .status(500)
                    .msg("发送失败")
                    .build();
        }

    }


    //模拟发送移库任务到wcs
    @Transactional
    public Resp sendMoveTask() {
        if (ppMoveMissionRepository.findAll().size() != 0) {
            PPMoveMission ppMoveMission = ppMoveService.findNewMoveMission();
            PPWmsTask ppWmsTask = ppMoveService.getPPWmsTask(ppMoveMission);
            saveTaskResult(ppWmsTask);
            ppWmsToWcs.saveToMissionHistory(ppWmsTask, 3);
            ppInoundMissionRepository.deletePPInboundMissionByMissionCode(ppWmsTask.getWmsTaskId());
            return Resp.builder()
                    .status(200)
                    .msg("发送成功")
                    .build();
        } else {
            return Resp.builder()
                    .status(500)
                    .msg("发送失败")
                    .build();
        }

    }

    //保存任务结果，用于taskStart中status的判断
    public void saveTaskResult(PPWmsTask wmsTask) {
        PPTaskResult taskResult = new PPTaskResult();
        taskResult.setWmsTaskId(wmsTask.getWmsTaskId());
        taskResult.setWcsTaskType(wmsTask.getWcsTaskType());
        taskResult.setLpnCode(wmsTask.getLpnCode());
        taskResult.setFromLocation(wmsTask.getFromLocation());
        taskResult.setToLocation(wmsTask.getToLocation());
        taskResult.setCreated(LocalDateTime.now());
        //设置为status2，方便taskStart中status的判断为2，不用手动修改数据库
        taskResult.setStatus(2);
        ppTaskResultService.saveTaskResult(taskResult);
    }


    //模拟码垛机进行任务
    @Transactional
    public Resp taskStart() {
        PPTaskResult taskResult = ppTaskResultRepository.findAll().get(0);
//        taskResult = null;
        if (ObjectUtil.isEmpty(taskResult)) {
            // 获取失败
            return new Resp().builder()
                    .status(200)
                    .msg("获取失败")
                    .build();
        } else {
//            ppLog.info("查询到的该条任务之前的状态：{}", taskResult);
//            ppTaskResultRepository.updateTaskResult(taskResult.getFromLocation(), taskResult.getToLocation(), taskResult.getStatus(), taskResult.getLastUpdated(), taskResult.getWmsTaskId());
            // 判断任务类型，保存出库入库的完成时间

            Integer taskType = taskResult.getWcsTaskType();
            // 入库任务
            if (taskType == 1) {

                //取货完成释放站点
//                if (taskResult.getStatus() == 1) {
//                    ppStationRepository.refeaseStation(taskResult.getFromLocation());
//                    ppLog.info("堆垛机取货成功,释放工作站：{}", taskResult);
//                }


                if (taskResult.getStatus() == 2) {
                    ppStationService.refeaseStation(taskResult.getFromLocation());

                    ppLog.info("堆垛机取货成功,释放工作站：{}", taskResult);

                    ppLog.info("收到入库任务反馈，开始更新历史任务，储位，以及库存");
                    // 任务结束记录
                    int ppInboundMissionHistoryResult = ppInoundMissionHistoryRepository.updateFinishTime(LocalDateTime.now(), taskResult.getWmsTaskId(), "任务完成");
                    ppLog.info("更新的历史入库任务条数：{}", ppInboundMissionHistoryResult);
                    //释放储位
                    String storageCode = taskResult.getToLocation();
                    int storageResult = ppStorageService.openStorage(storageCode);
                    ppLog.info("更新的储位条数：{}", storageResult);

                    //入库信息补全
                    String palletCode = taskResult.getLpnCode();
                    PpPallet ppPallet = ppPalletRepository.findByPalletCode(palletCode);
                    ppLog.info("载盘已进入库区，当前载盘：{}", ppPallet);

                    //先判断载盘有没有绑定pp
                    if (ppPallet.getPpBatch() == null || ppPallet.getPpBatch().trim().isEmpty()) {
                        ppLog.info("该载盘没有绑定pp，是空载盘入库");
                        //空载盘入库，不需要记录库存信息
                        // 更新储位的信息
                        ppStorageService.finishInBoundNullPallet(ppPallet.getPalletCode(), storageCode);

                    } else {
                        //入库存
                        InBoundInfo inBoundInfo = new InBoundInfo();
                        inBoundInfo.setPalletCode(palletCode);
                        PPInfo ppInfo = ppInfoRepository.getPPInfoByPpBatch(ppPallet.getPpBatch());
                        inBoundInfo.setStationCode(taskResult.getFromLocation());
                        inBoundInfo.setIsPackage(ppInfo.getIsPakage());
                        ppInventoryService.savePPInventory(inBoundInfo, ppInfo, storageCode);
                        // 更新储位的信息
                        ppStorageService.finishInBound(ppPallet.getPalletCode(), storageCode);

                    }

                    ppTaskResultService.deleteByWmsTaskId(taskResult.getWmsTaskId());
                    ppWmsTaskRepository.deleteByWmsTaskId(taskResult.getWmsTaskId());

                }
                // 出库任务
            } else if (taskType == 2) {
                if (taskResult.getStatus() == 2) {
                    PpPallet ppPallet = ppPalletRepository.findByPalletCode(taskResult.getLpnCode());
                    //查询出库单
                    String missionCode = taskResult.getWmsTaskId();

                    PPStation ppStation = ppStationRepository.findByStationCode(taskResult.getToLocation());
                    //如果工作站类型是1就释放工作站
                    if (ppStation.getStationType() == 1) {
                        ppStationRepository.refeaseStation(ppStation.getStationCode());
                    }


                    //先判断是不是空载盘出库
                    if (ppPallet.getPpBatch() == null || ppPallet.getPpBatch().trim().isEmpty()) {

                        // 任务结束记录
                        ppOutBoundMissionHistoryRepository.updateFinishTime(LocalDateTime.now(), taskResult.getWmsTaskId(), "任务完成");
                        // 释放储位
                        ppStorageService.cleanStorage(taskResult.getFromLocation());

                        // 删除任务，任务状态。
                        ppOutBoundMissionRepository.deletePPOutboundMissionByMissionCode(missionCode);
                        ppTaskResultService.deleteByWmsTaskId(taskResult.getWmsTaskId());
                        ppWmsTaskRepository.deleteByWmsTaskId(taskResult.getWmsTaskId());

                    } else {

                        Integer orderId = ppOutBoundMissionRepository.findPPOutboundMissionByMissionCode(missionCode).getOutBoundOrderId();
                        List<PPOutboundMission> outBoundMissions = ppOutBoundMissionRepository.findPPOutboundMissionsByOutBoundOrderId(orderId);

                        if (outBoundMissions.size() == 1) {
                            if (orderId != null) {
                                ppLog.info("出库单：{}{}", orderId, "结束！");
                                ppOutBoundOrderService.finishOrder(orderId);
                            }
                        }

                        // 任务结束记录
                        ppOutBoundMissionHistoryRepository.updateFinishTime(LocalDateTime.now(), taskResult.getWmsTaskId(), "任务完成");
                        // 释放储位
                        ppStorageService.cleanStorage(taskResult.getFromLocation());

                        //更新库存状态
                        String palletCode = ppPallet.getPalletCode();
                        ppInventoryService.outBoundByPalletCode(palletCode);

                        // 删除任务，任务状态。
                        ppOutBoundMissionRepository.deletePPOutboundMissionByMissionCode(missionCode);
                        ppTaskResultService.deleteByWmsTaskId(taskResult.getWmsTaskId());
                        ppWmsTaskRepository.deleteByWmsTaskId(taskResult.getWmsTaskId());

                        //解绑载盘，如果工作站类型是1就要把载盘也给删除
                        if (ppStation.getStationType() == 1) {
                            ppPalletRepository.deleteByPalletCode(palletCode);
                        }


//                        }else {
//                            ppPalletService.unBindPallet(palletCode);
//                        }

                    }
                }
                //移库任务
            } else if (taskType == 3) {
                if (taskResult.getStatus() == 2) {
                    //查询移库单
                    ppLog.info("收到移库任务反馈，开始更新历史任务，储位，以及库存");

                    //释放储位
                    ppStorageService.cleanStorage(taskResult.getFromLocation());


                    //更改库存位置信息
                    PPInventory ppInventory = ppInventoryRepository.findPPInventoryByStorageCode(taskResult.getFromLocation());
                    ppInventory.setStorageCode(taskResult.getToLocation());
                    //取消库存禁用
                    ppInventory.setLockStatus(1);
                    ppInventoryRepository.save(ppInventory);

                    // 更新储位的信息
                    ppStorageService.finishInBound(taskResult.getLpnCode(), taskResult.getToLocation());
                    ppTaskResultService.deleteByWmsTaskId(taskResult.getWmsTaskId());

                    //移库任务完成后，取消禁用储位
                    int storageResult = ppStorageService.openStorage(taskResult.getToLocation());
                    ppLog.info("更新的储位条数：{}", storageResult);

                    //删除移库任务
                    ppMoveMissionRepository.deletePPMoveMissionByMissionCode(taskResult.getWmsTaskId());


                    // 任务结束记录
                    int ppMoveMissionHistoryResult = ppMoveMissionRepository.updateFinishTime(LocalDateTime.now(), taskResult.getWmsTaskId(), "任务完成");
                    ppLog.info("更新的历史移库任务条数：{}", ppMoveMissionHistoryResult);

                }

            }

            return Resp.builder()
                    .status(200)
                    .msg("success")
                    .build();
        }


    }


}
